package com.qf.commons.web.apiversion;

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;

/**
 * description: 支持接口多版本的Controller映射器（对原有的RequestMappingHandlerMapping的拓展）
 * author: Ken
 * 公众号：Java架构栈
 */
public class ApiVersionHandlerMapping extends RequestMappingHandlerMapping {

    /**
     * 时机：Spring容器初始化时触发
     *
     * 工程中，所有的Controller都会“调用”该方法，根据当前的Controller的类信息，
     * 返回一个开发者自定义的RequestCondition(请求条件)对象
     *
     * @param handlerType - Controller的Class对象    10个Controller
     * @return
     */
    @Override
    protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        //获取类上的版本注解
        ApiVersion apiVersion = AnnotationUtils.getAnnotation(handlerType, ApiVersion.class);
        //将注解上的版本号设置给条件对象
        return new ApiVersionRequestCondition(apiVersion != null ? apiVersion.value() : 1.0);
    }

    /**
     * 时机：Spring容器初始化时触发
     *
     * 工程中，所有Controller中的所有方法，都会依次"调用"该方法，根据当前的方法信息，
     *  返回一个符合该方法的RequestCondition（请求匹配条件）对象
     *
     * @param method - 依次是Controller中的所有方法
     * @return
     */
    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        //获取方法上的版本注解
        ApiVersion apiVersion = AnnotationUtils.getAnnotation(method, ApiVersion.class);
        //如果方法的版本注解为null，则再去尝试获取类上的注解
        if (apiVersion == null) {
            //获取该方法类上的注解
            apiVersion = AnnotationUtils.getAnnotation(method.getDeclaringClass(), ApiVersion.class);
        }

        //将注解上的版本号设置给条件对象
        return new ApiVersionRequestCondition(apiVersion != null ? apiVersion.value() : 1.0);
    }
}
